package org.vectrics.recruiter.struts;

import java.util.Date;
import java.util.Iterator;

import org.apache.log4j.Logger;
import org.vectrics.SystemException;
import org.vectrics.common.util.DateSync;
import org.vectrics.company.Company;
import org.vectrics.company.CompanyPerson;
import org.vectrics.company.CompanyPersonRoleType;
import org.vectrics.company.Sector;
import org.vectrics.dataweb.WebServiceAction;
import org.vectrics.domain.Domain;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.struts.Request;
import org.vectrics.system.SystemConstant;
import org.vectrics.user.ContactInfo;
import org.vectrics.user.Person;
import org.vectrics.user.PersonPrivilegeGroup;
import org.vectrics.user.PersonPrivilegeGroupType;
import org.vectrics.user.User;
import org.vectrics.user.UserPrivilege;
import org.w3c.dom.Element;

/**
 * Respond to XML Service request to establish a new hosted site.
 * 
 * @author Mike Moore
 * 
 */
public class HostedSiteWebService extends WebServiceAction {
    private transient Logger log = Logger.getLogger(this.getClass());

    public HostedSiteWebService() {
        super();
    }

    public void getData(Request request, String command, Element requestElement, Element responseElement) {
        ThreadProperties.setSystemUser(true);
        ThreadProperties.setPerson(CoreServiceLocator.getConfiguration().getSystemPerson());

        log.info("Command: " + command);
        if (command.equals("establish.hosted.site")) {
            log.info("Command to establish new site");

            Element siteInfoElement = (Element) requestElement.getElementsByTagName("siteInfo").item(0);
            String companyName = siteInfoElement.getAttribute("companyName");
            String companySectorCode = siteInfoElement.getAttribute("companySectorCode");
            Element adminElement = (Element) requestElement.getElementsByTagName("adminPerson").item(0);
            String adminLastName = adminElement.getAttribute("lastname");
            String adminFirstName = adminElement.getAttribute("firstname");
            String adminEmail = adminElement.getAttribute("email");
            String adminUserName = adminElement.getAttribute("userName");
            String adminPassword = adminElement.getAttribute("password");

            Sector sector = CoreServiceLocator.getCompanyService().findSector(companySectorCode);
            if (sector == null) {
                throw new SystemException("Exception finding sector: " + companySectorCode);
            }

            String domainName = findUniqueDomainName(companyName);

            log.info("Create a data owner - using system company as temporary company");
            Domain domain = new Domain();
            domain.setDescription(domainName);
            domain.setPrimaryCompany(CoreServiceLocator.getSystemService().findSystemDomain().getPrimaryCompany());
            domain.setParent(CoreServiceLocator.getSystemService().findSystemDomain());
            CoreServiceLocator.getSystemService().updateDomain(domain);

            setDefaultSystemValuesForNewSite(domain);

            // Create admin user
            Person person = new Person();
            person.setFirstName(adminFirstName);
            person.setLastName(adminLastName);
            person.setDomain(domain);
            person.setLocale("en");
            CoreServiceLocator.getPersonService().updatePerson(person);
            // ThreadProperties.forcedCommit();

            User user = person.createUserIfNotExist();
            user.setUserName(adminUserName);
            user.setPassword(adminPassword);
            user.setPasswordEncrypted(true);
            CoreServiceLocator.getPersonService().updatePerson(person);

            ContactInfo contactInfo = person.createContactInfoIfNotExist();
            contactInfo.setEmail(adminEmail);
            CoreServiceLocator.getPersonService().updatePerson(person);

            log.debug("Create company");
            Company company = CoreServiceLocator.getCompanyService().createCompany(domain, companyName, null, sector);
            CoreServiceLocator.getCompanyService().updateCompany(company);
            // ThreadProperties.forcedCommit();

            log.debug("Change primary company for domain to the one that was just created for this new site");
            domain.setPrimaryCompany(company);
            CoreServiceLocator.getSystemService().updateDomain(domain);

            CompanyPerson companyPerson = new CompanyPerson();
            companyPerson.setCompany(company);
            companyPerson.setPerson(person);
            CoreServiceLocator.getCompanyService().updateCompanyPerson(companyPerson);

            companyPerson.addRole(CoreServiceLocator.getCompanyService().findCompanyPersonRoleType(
                    CompanyPersonRoleType.ROLE_EMPLOYEE), new Date());
            CoreServiceLocator.getCompanyService().updateCompanyPerson(companyPerson);
            // ThreadProperties.forcedCommit();

            PersonPrivilegeGroup group = new PersonPrivilegeGroup();
            group.setGlobal(true);
            group.setDomain(company.getDomain());
            group.setPerson(person);
            group.setDateStart(DateSync.getCurrentTime());
            PersonPrivilegeGroupType type = CoreServiceLocator.getPersonService().findPersonPrivilegeGroupType("admin");
            group.setPersonPrivilegeGroupType(type);
            CoreServiceLocator.getPersonService().updatePersonPrivilegeGroup(group);

            CoreServiceLocator.getPersonService().addDefaultUserPrivileges(group);
            log.info("Number of privileges added: " + person.getPrivileges().size());

            Iterator iter = person.getPrivileges().iterator();
            while (iter.hasNext()) {
                UserPrivilege userPrivilege = (UserPrivilege) iter.next();
                if (userPrivilege.getId() == null) {
                    log.info("Updating role: \r\n" + "  - Person:    " + userPrivilege.getPerson().getName()
                            + "  - Role:      " + userPrivilege.getPrivilegeType().getCode() + "  - Dt Strt:   "
                            + userPrivilege.getDateStart() + "  - Dataowner: "
                            + userPrivilege.getDomain().getDescription());
                    CoreServiceLocator.getPersonService().updateUserPrivilege(userPrivilege);
                }
            }

            log
                    .debug("Blank out system constants that should not have values copied from parent, these values will need to be set later");
            SystemConstant systemConstant = CoreServiceLocator.getSystemService().findSystemConstant(domain,
                    "resume.recipient.email.addr");
            systemConstant.setValue("unspecified");
            CoreServiceLocator.getSystemService().updateSystemConstant(systemConstant);

            systemConstant = CoreServiceLocator.getSystemService().findSystemConstant(domain,
                    "resume.recipient.email.host");
            systemConstant.setValue("");
            CoreServiceLocator.getSystemService().updateSystemConstant(systemConstant);

            systemConstant = CoreServiceLocator.getSystemService().findSystemConstant(domain,
                    "resume.recipient.email.password");
            systemConstant.setValue("unspecified");
            CoreServiceLocator.getSystemService().updateSystemConstant(systemConstant);

            systemConstant = CoreServiceLocator.getSystemService().findSystemConstant(domain, "mail.from.address");
            systemConstant.setValue("");
            CoreServiceLocator.getSystemService().updateSystemConstant(systemConstant);

            systemConstant = CoreServiceLocator.getSystemService().findSystemConstant(domain, "mail.from.name");
            systemConstant.setValue("");
            CoreServiceLocator.getSystemService().updateSystemConstant(systemConstant);

            systemConstant = CoreServiceLocator.getSystemService().findSystemConstant(domain, "mail.host");
            systemConstant.setValue("");
            CoreServiceLocator.getSystemService().updateSystemConstant(systemConstant);

            systemConstant = CoreServiceLocator.getSystemService().findSystemConstant(domain, "mail.user");
            systemConstant.setValue("unspecified");
            CoreServiceLocator.getSystemService().updateSystemConstant(systemConstant);
            ThreadProperties.forcedCommit();

            Element domainElement = responseElement.getOwnerDocument().createElement("domain");
            this.getDataElement(responseElement).appendChild(domainElement);
            domainElement.setAttribute("id", domain.getId().toString());
            domainElement.setAttribute("description", domain.getDescription());
        } else {
            throw new SystemException("Do not know how to handle command: " + command);
        }

    }

    /**
     * Find a unique domain name (a name not in the database) that begins with
     * the name passed to this method.
     * 
     * @param companyName
     * @return the unique name.
     */
    private String findUniqueDomainName(String companyName) {
        log.info("See if domain already exists, if so adjust the domain name and test again until a new name is found");
        String adjustedName = companyName;
        int suffix = 1;
        boolean doneTesting = false;
        while (!doneTesting) {
            Domain domain = CoreServiceLocator.getSystemService().findDomainForName(adjustedName);
            if (domain == null) {
                log.debug("Domain name is unique, starting");
                doneTesting = true;
            } else {
                adjustedName = companyName + " - " + suffix;
            }
            suffix++;
        }
        log.info("Requested domain name: " + companyName + "  Adjusted name: " + adjustedName);
        return (adjustedName);
    }

    private void setDefaultSystemValuesForNewSite(Domain domain) {
        // SystemConstant systemConstant =
        // CoreServiceLocator.getSystemService().findSystemConstant(domain, "");

    }

}
